package com.ybkj.daijia.api.driver.v4;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ybkj.daijia.api.baidu.BaiduApi;
import com.ybkj.daijia.api.driver.transport.ResultTransport;
import com.ybkj.daijia.api.util.ErrorConstantV4;
import com.ybkj.daijia.cache.DriverCache;
import com.ybkj.daijia.cache.MyCacheManager;
import com.ybkj.daijia.cache.SmallLocationService;
import com.ybkj.daijia.common.Distance;
import com.ybkj.daijia.common.OrderLocationGroup;
import com.ybkj.daijia.server.event.model.DriverUpdateLocationEvent;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.DriverLogin;
import com.ybkj.daijia.server.model.OrderLocation;
import com.ybkj.daijia.server.service.DriverLoginService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.OrderLocationService;
import com.ybkj.daijia.server.zhuan.SelectPrice;
import com.ybkj.daijia.server.zhuan.SmallLocation;
import com.ybkj.daijia.serverUtils.HttpClientUtil;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller("LocationControllerV4")
@RequestMapping(value = "driver/api/rest/v4")
@Slf4j
public class LocationController {

    private static final Logger locationLogger = LoggerFactory.getLogger("location");

    @Autowired
    private DriverService driverService;

    @Autowired
    private DriverLoginService driverLoginService;

    @Autowired
    private OrderLocationService orderLocationService;

    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;

    @Autowired
    private MyCacheManager cacheManager;
    @Autowired
    private BaiduApi baiduApi;

    @Autowired
    private SmallLocationService smallLocationService;

    /***
     * 更新指定司机的坐标位置
     * @param employToken
     * @param longitude
     * @param latitude
     * @param locDate 上传时间
     * @return
     */
    @RequestMapping(value = "updateEmployLocation", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport updateUserLocation(
        String employToken, Double longitude, Double latitude, Long locDate,
        HttpServletRequest httpServletRequest) {

        if (StringUtils.isBlank(employToken) || null == longitude || null == latitude) {
            return ResultTransport.getErrorBy(ErrorConstantV4.PARAM_ERROR);
        }

        DriverLogin driverLogin = driverLoginService.selectByToken(employToken);

        if (null == driverLogin) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_ERROR);
        }

        if (System.currentTimeMillis() >= driverLogin.getDeathDate().getTime()) {
            return ResultTransport.getErrorBy(ErrorConstantV4.TOKEN_TIME_ERROR);
        }

        Driver driver = driverService.findOne(driverLogin.getDriverId());

        if (null == driver) {
            return ResultTransport.getErrorBy(ErrorConstantV4.EMPLOY_NOT_EXISTS);
        }

        locationLogger.info("recv driverId:{},Longitude:{},Latitude:{},locDate,{}",
            driver.getId(), longitude, latitude, locDate);
//		System.out.println("driverId [" + driver.getId() + "] " + new Date());
//		String date = httpServletRequest.getHeader("Date");
//		System.out.println("----------" + date);
//		Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
//		while(headerNames.hasMoreElements()) {
//			String s = headerNames.nextElement();
//			System.out.println(s + "  " + httpServletRequest.getHeader(s));
//		}

        try {

            if (latitude > 3 && latitude < 54 && longitude > 73 && longitude < 136) {

                String address = null;

                Double lastLat = driver.getLastLatitude();
                Double lastLng = driver.getLastLongitude();

                if (lastLat == null || lastLng == null) {
                    lastLat = latitude;
                    lastLng = longitude;
                    address = HttpClientUtil.getPlaceByLngAndLat(longitude, latitude);//查询地址信息

                    driverService.updateLocation(longitude, latitude, lastLng, lastLat, address,
                        driver.getId());

                    DriverUpdateLocationEvent updateLocationEvent = new DriverUpdateLocationEvent(
                        driver, latitude, longitude, address);
                    applicationEventMulticaster.multicastEvent(updateLocationEvent);
                } else {
                    double distance = Distance.doubleVal(latitude, longitude, lastLat, lastLng);
                    if (distance >= 0.1) {
                        lastLat = latitude;
                        lastLng = longitude;
                        address = HttpClientUtil.getPlaceByLngAndLat(longitude, latitude);//查询地址信息

                        driverService.updateLocation(longitude, latitude, lastLng, lastLat, address,
                            driver.getId());

                        DriverUpdateLocationEvent updateLocationEvent = new DriverUpdateLocationEvent(
                            driver, latitude, longitude, address);
                        applicationEventMulticaster.multicastEvent(updateLocationEvent);
                    }
                }
            }

            if (null == driver.getPosUpdated() || (
                System.currentTimeMillis() - driver.getPosUpdated().getTime() > 10000)) {
                driverService.updatePosUpdated(driver.getId(), new Date());
            }

            DriverCache driverCache = cacheManager.getDriverCache(driver.getId());
            if (driverCache != null && locDate != null) {
                driverCache.setDriverLat(latitude);
                driverCache.setDriverLng(longitude);
                if (null == driverCache.getSelectPrice().getEndRun() && null != driverCache
                    .getSelectPrice().getStartRun()) {
                    synchronized (driverCache) {
                        SmallLocation smallLocation = new SmallLocation();
                        smallLocation.setLongitude(longitude);
                        smallLocation.setLatitude(latitude);
                        smallLocation.setLocDate(locDate);
                        List<SmallLocation> smallLocations = driverCache.getDriverLocationList();
                        boolean valid = false;
                        if (0 == smallLocations.size()) {
                            smallLocations.add(smallLocation);
                            valid = true;
                        } else {
                            SmallLocation last = smallLocations.get(smallLocations.size() - 1);
                            if (smallLocationService
                                .filterTheSameLocationAndTime(smallLocation, last)) {
                                smallLocations.add(smallLocation);
                                valid = true;
                            }
                        }
                        if (!valid) {
                            return ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
                        }
//						driverCache.putDriverLocation(smallLocation);
                        if (locationLogger.isInfoEnabled()) {
                            locationLogger
                                .info("Estimated price dr{}, {}", driver.getId(), smallLocation);
                        }

                        Double aDouble = smallLocationService.filterAndComputeMiles(
                            new ArrayList<>(driverCache.getDriverLocationList()), false,
                            driverCache.getOrderId());

//						smallLocationService.synComputeMileAndComputePrice(smallLocation, driverCache);
                        SelectPrice selectPrice = driverCache.getSelectPrice();
                        selectPrice.setRunKilometers(aDouble / 1000);
                        smallLocationService.freshSelectPrice(driverCache);
//						Map<String, Double> map = smallLocationService.comparteAndComputeTwoSmallLocations(smallLocation, lastedLocation);
//						if (map != null) {
//							Double thisKiloMiles = map.get("kilo");
//							if (thisKiloMiles != null) {
//								driverCache.setRunKiloMilters(driverCache.getRunKiloMilters() + thisKiloMiles);
//							}
//						}
						cacheManager.saveOrUpdateObj(driverCache);
					}
				}
			}


			return ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS); // 更新坐标

		} catch (Exception e) {
			log.error("api v4 driver updateUserLocation error: {}", e);
			return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
		}

    }


    /**
     *
     */
    @RequestMapping(value = "updateOrderLocation", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport updateOrderLocation(HttpServletRequest req) {

        String str = "";
        try {

            InputStream is = req.getInputStream();
            GZIPInputStream gzin = new GZIPInputStream(is);

            InputStreamReader isr = new InputStreamReader(gzin, "UTF-8");
            BufferedReader br = new BufferedReader(isr);
            StringBuffer sb = new StringBuffer();
            String tempbf;
            while ((tempbf = br.readLine()) != null) {
                sb.append(tempbf);
            }
            isr.close();
            gzin.close();
            str = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (StringUtils.isNotBlank(str)) {
            try {

                Gson gson = new Gson();
                List<OrderLocationGroup> locs = gson
                    .fromJson(str, new TypeToken<List<OrderLocationGroup>>() {
                    }.getType());

                List<Long> returnIds = new ArrayList<Long>();

                if (!CollectionUtils.isEmpty(locs)) {
                    List<OrderLocation> list = new ArrayList<OrderLocation>();
                    for (OrderLocationGroup og : locs) {
                        returnIds.add(og.getId());

                        String orderIds = og.getOrderIds();
                        String orderType = og.getOrderType();
                        String[] orderIdsArr = orderIds.split(",");
                        String[] orderTypeArr = orderType.split(",");
                        for (int i = 0; i < orderIdsArr.length; i++) {
                            OrderLocation orderLocation = new OrderLocation();
                            orderLocation.setOrderId(Long.valueOf(orderIdsArr[i]));
                            orderLocation
                                .setOrderType(OrderLocation.OrderType.valueOf(orderTypeArr[i]));

                            orderLocation.setSortId(og.getId());
                            orderLocation.setLatitude(og.getLatitude());
                            orderLocation.setLongitude(og.getLongitude());
                            orderLocation.setRadius(og.getRadius());
                            orderLocation.setDirection(og.getDirection());
                            orderLocation.setLocType(og.getLocType());
                            orderLocation.setLocDate(new Date(og.getLocDate()));
//							orderLocationService.save(orderLocation);
                            list.add(orderLocation);
                        }
                    }
                    orderLocationService.saveList(list);
                }

                String ids = "";
                if (!CollectionUtils.isEmpty(returnIds)) {
                    ids = StringUtils.join(returnIds.toArray(), ",");
                }

                Map<String, Object> returnMap = new HashMap<String, Object>();
                returnMap.put("ids", ids);

                ResultTransport instance = ResultTransport.getErrorBy(ErrorConstantV4.SUCCESS);
                instance.setData(returnMap);

                return instance;

            } catch (Exception e) {
                log.error("api v4 driver updateOrderLocation error: {}", e);
                return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
            }
        } else {
            return ResultTransport.getErrorBy(ErrorConstantV4.SERVER_ERROR);
        }

	}
	
}
